﻿using Windows.System;
using Microsoft.UI.Xaml.Input;

namespace DimensionsHelper.Client.WinUi.Views;

public sealed partial class ShellPage : Page
{
    public ShellPage(ShellViewModel viewModel)
    {
        ViewModel = viewModel;
        InitializeComponent();
        SetNavigationItems();

        ViewModel.NavigationService.Frame = NavigationFrame;
        ViewModel.NavigationViewService.Initialize(NavigationViewControl);

        App.MainWindow.ExtendsContentIntoTitleBar = true;
        App.MainWindow.SetTitleBar(AppTitleBar);
        App.MainWindow.Activated += MainWindow_Activated;
        AppTitleBarText.Text = ResourceKeys.AppDisplayName.GetLocalized();
    }

    public ShellViewModel ViewModel
    {
        get;
    }


    public NavigationView NavigationView => NavigationViewControl;

    public void UpdateSettingItemContent(bool hide = false)
    {
        if (NavigationViewControl.SettingsItem is NavigationViewItem item)
        {
            item.Content = hide ? null : ResourceKeys.SettingsContent.GetLocalized();
        }
    }


    private void SetNavigationItems()
    {
        PageInfo[] pages = PageInfoDataSource.Instance.GetPageInfos();
        foreach (PageInfo page in pages)
        {
            if (page.WithSeparator)
            {
                NavigationView.MenuItems.Add(new NavigationViewItemSeparator());
            }

            NavigationView.MenuItems.Add(CreateNavigationItem(page));
        }
    }


    private static NavigationViewItem CreateNavigationItem(PageInfo pageInfo)
    {
        NavigationViewItem item = new()
        {
            Content = pageInfo.Title,
            Icon = new FontIcon
            {
                FontFamily = FontHelper.FluentUiSystemFont,
                FontSize = 24,
                Height = 24,
                Width = 24,
                Glyph = pageInfo.Character
            }
        };

        NavigationHelper.SetNavigateTo(item, pageInfo.FullTypeName);

        foreach (PageInfo subPage in pageInfo.SubPages)
        {
            if (subPage.WithSeparator)
            {
                item.MenuItems.Add(new NavigationViewItemSeparator());
            }

            item.MenuItems.Add(CreateNavigationItem(subPage));
        }

        return item;
    }


    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        TitleBarHelper.UpdateTitleBar(RequestedTheme);

        KeyboardAccelerators.Add(BuildKeyboardAccelerator(VirtualKey.Left, VirtualKeyModifiers.Menu));
        KeyboardAccelerators.Add(BuildKeyboardAccelerator(VirtualKey.GoBack));

        UpdateSettingItemContent();
        App.SetCurrentNavigationMode(App.IsCurrentNavigationLeftMode());
    }

    private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
    {
        App.AppTitleBar = AppTitleBar;
        App.AppTitleBarText = AppTitleBarText;

        VisualStateManager.GoToState(this,
            args.WindowActivationState == WindowActivationState.Deactivated ? "Deactivated" : "Activated", true);
    }

    private void NavigationViewControl_DisplayModeChanged(NavigationView sender,
        NavigationViewDisplayModeChangedEventArgs args)
    {
        AppTitleBar.Margin = new Thickness
        {
            Left = sender.CompactPaneLength * (sender.DisplayMode == NavigationViewDisplayMode.Minimal ? 2 : 1),
            Top = AppTitleBar.Margin.Top,
            Right = AppTitleBar.Margin.Right,
            Bottom = AppTitleBar.Margin.Bottom
        };
    }

    private static KeyboardAccelerator BuildKeyboardAccelerator(VirtualKey key, VirtualKeyModifiers? modifiers = null)
    {
        KeyboardAccelerator? keyboardAccelerator = new() { Key = key };

        if (modifiers.HasValue)
        {
            keyboardAccelerator.Modifiers = modifiers.Value;
        }

        keyboardAccelerator.Invoked += OnKeyboardAcceleratorInvoked;

        return keyboardAccelerator;
    }

    private static void OnKeyboardAcceleratorInvoked(KeyboardAccelerator sender,
        KeyboardAcceleratorInvokedEventArgs args)
    {
        INavigationService? navigationService = App.GetService<INavigationService>();

        bool result = navigationService.GoBack();

        args.Handled = result;
    }
}